﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Mimoza.AgentLayer.Communication;
using Mimoza.Transport;

namespace Mimoza.ServiceLayer
{
    class ServiceHostRegistration : BaseObject
    {
        public ServiceHostRegistration(Configuration config)
            : base(config)
        {
            RequestBroadcastServerAddress.RegisterHandler(
                new RequestBroadcastServerAddress.Handler(
                    ProcessRequestServerAddress));
            RequestSetServerAddress.RegisterInTransport();

            RequestRegisterNewHost.RegisterHandler(
                new RequestRegisterNewHost.Handler(ProcessRequestNewHostRegister));
            ReplyRegisterNewHost.RegisterInTransport();
        }

        override public void Init()
        {
        }

        override public void Shutdown()
        {
        }


        TransferObject ProcessRequestServerAddress(RequestBroadcastServerAddress request)
        {
            Common.Logger.Log.Info("ServiceHostRegistration new host: id - '"
                + request.HostId + "' remoteAddr - '"
                + request.RemoteAddress + "'.");

            // send server addr to host
            int agentUDPPort = (request.AgentUDPPort != 0) ? request.AgentUDPPort :
                Configuration.Settings.BroadcastTransportPort;

            Connection reverseUdpConn = Mimoza.Transport.Transport.CreateUDPConnection(
                request.RemoteAddress, agentUDPPort);

            reverseUdpConn.SendRequest(
                new RequestSetServerAddress(request.HostId, LocalInfo.HostName, ""));

            reverseUdpConn.Close();

            return null;
        }

        ReplyRegisterNewHost ProcessRequestNewHostRegister(RequestRegisterNewHost request)
        {
            Common.Logger.Log.Info("ServiceHostRegistration new host register: id - '"
                + request.HostId + "' remoteAddr - '"
                + request.RemoteAddress + "'.");

            string requestHostId = request.HostId;
            string hostId = request.HostId;

            FindHostByMAC(hostId, request.MacAddresses, ref hostId);

            ReplaceHost(hostId, 
                request.HostName, request.RemoteAddress,
                request.MacAddresses, request.IPAddresses,
                request.OSName, request.ModelName, request.ModelVersion);

            Common.Logger.Log.Info("ServiceHostRegistration new host register...OK");

            ReplyRegisterNewHost reply = new ReplyRegisterNewHost(request.HostId);
            if (hostId != request.HostId) reply.OverrrideHostId = hostId;

            return reply;
        }

        void ReplaceHost(string hostId, string hostName, string hostRemoteAddress, 
            string macAddrs, string ipAddrs, string osName, string modelName, string modelVersion)
        {
            Common.Logger.Log.Info("ServiceHostRegistration.ReplaceHost: id - '"
                + hostId + 
                "'\n\t addr - '" + hostRemoteAddress + 
                "'\n\t hostName -'" + hostName +
                "'\n\t macAddrs - '" + macAddrs +
                "'\n\t ipAddrs - '" + ipAddrs +
                "'\n\t osName - '" + osName +
                "'\n\t modelName - '" + modelName +
                "'\n\t modelVersion - '" + modelVersion +
                "'.");

            ObjectLayer.Host host = null;
            bool bHostExists = true;

            host = Configuration.ObjectLayer.HostRepository.GetHostByID(new Guid(hostId));
            if (host == null)
            {
                bHostExists = false;
                host = Configuration.ObjectLayer.HostRepository.CreateHost(
                    new Guid(hostId));

                host.Parent = ObjectLayer.ContainerRepository.DefaultHostContainer;
            }

            host.Name = hostName;
            host.IPAddress = hostRemoteAddress;
            host.MACAddress = macAddrs;
            host.IPAddress = ipAddrs;
            host.OS = osName;
            host.Model = modelName;
            host.Version = modelVersion;

            using (new NotificationAutoSet("MACAddress"))
            {
                if (bHostExists)
                    Configuration.ObjectLayer.HostRepository.Update(host);
                else
                    Configuration.ObjectLayer.HostRepository.Add(host);
            }
        }

        bool FindHostByName(string hostId, string hostName, ref string existHostId)
        {
            if (Configuration.ObjectLayer.HostRepository.GetHostByID(new Guid(hostId)) != null)
            {
                return false;
            }

            bool res = false;

            ObjectLayer.Host host = Configuration.ObjectLayer.HostRepository.GetHostByName(hostName);
            if (host!=null)
            {
                res = true;
                existHostId = host.ID.ToString();
            }

            Common.Logger.Log.Info("ServiceHostRegistration.FindHostByName: name - '"
                + hostName + "' addr - '" + existHostId + "' result - " + res.ToString() + ".");
            if (res)
            {
                Common.Logger.Log.Info("ServiceHostRegistration.FindHostByName: name - '"
                    + hostName + "' allready registered.");
            }
            
            return res;
        }

        bool FindHostByMAC(string hostId, string hostMac, ref string existHostId)
        {
            if (Configuration.ObjectLayer.HostRepository.GetHostByID(new Guid(hostId)) != null)
            {
                return false;
            }

            bool res = false;

            ObjectLayer.Host host = Configuration.ObjectLayer.HostRepository.GetHostByMAC(hostMac);
            if (host != null)
            {
                res = true;
                existHostId = host.ID.ToString();
            }

            Common.Logger.Log.Info("ServiceHostRegistration.FindHostByMAC: mac - '"
                + hostMac + "' addr - '" + existHostId + "' result - " + res.ToString() + ".");
            if (res)
            {
                Common.Logger.Log.Info("ServiceHostRegistration.FindHostByMAC: mac - '"
                    + hostMac + "' allready registered.");
            }

            return res;
        }

    }
}
